/**
 * socketio-client.js - WebSocket client for real-time device monitoring
 * 
 * This module handles WebSocket connections to the device server for real-time
 * updates on device status, screenshots, and other monitoring information.
 */

class SocketIOClient {
    constructor(socketUrl = null) {
        this.socket = null;
        this.connected = false;
        this.eventHandlers = {};
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 5;
        this.reconnectDelay = 2000; // Start with 2 seconds
        
        // Default socket URL if not provided
        this.socketUrl = socketUrl || this._getDefaultSocketUrl();
    }
    
    /**
     * Get the default WebSocket URL based on the current page location
     */
    _getDefaultSocketUrl() {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const host = window.location.hostname;
        let port = window.location.port;
        if (!port) {
            port = window.location.protocol === 'https:' ? '443' : '80';
        }
        return `${protocol}//${host}:${port}`;
    }
    
    /**
     * Initialize the WebSocket connection
     */
    connect() {
        if (this.socket) {
            this.disconnect();
        }
        
        try {
            console.log(`Connecting to WebSocket server at ${this.socketUrl}`);
            this.socket = io(this.socketUrl, {
                // transports: ['websocket'], // Temporarily commented out for diagnosis
                reconnection: true,
                reconnectionAttempts: this.maxReconnectAttempts,
                reconnectionDelay: this.reconnectDelay
            });
            
            // Setup event handlers
            this.socket.on('connect', () => {
                console.log('Connected to device WebSocket server');
                this.connected = true;
                this.reconnectAttempts = 0;
                this._triggerEvent('connect');
            });
            
            this.socket.on('disconnect', (reason) => {
                console.log(`Disconnected from device WebSocket server: ${reason}`);
                this.connected = false;
                this._triggerEvent('disconnect', reason);
            });
            
            this.socket.on('connect_error', (error) => {
                console.error('WebSocket connection error. Full error object:', error);
                if (error && error.message) {
                    console.error('Error message:', error.message);
                }
                if (error && error.description) {
                    console.error('Error description:', error.description);
                }
                if (error && error.type) {
                    console.error('Error type:', error.type); // e.g., 'TransportError'
                }
                this._triggerEvent('error', error);
                
                // Handle reconnection
                this.reconnectAttempts++;
                if (this.reconnectAttempts >= this.maxReconnectAttempts) {
                    console.error('Max reconnection attempts reached');
                    this._triggerEvent('max_reconnect_attempts');
                }
            });
            
            // Device-specific events
            this.socket.on('reload_devices', (data) => {
                console.log('reload_devices:', data);
                this._triggerEvent('reload_devices', data);
            });
            
            return true;
        } catch (error) {
            console.error('Failed to connect to WebSocket server:', error);
            this._triggerEvent('error', error);
            return false;
        }
    }
    
    /**
     * Disconnect from the WebSocket server
     */
    disconnect() {
        if (this.socket) {
            this.socket.disconnect();
            this.socket = null;
            this.connected = false;
        }
    }
    
    /**
     * Request the current device list from the server
     */
    requestDeviceList() {
        if (!this.connected) {
            console.warn('Cannot request device list: not connected');
            return false;
        }
        
        this.socket.emit('request_device_list');
        return true;
    }
    
    /**
     * Request status for a specific device
     * @param {string} deviceId - The ID of the device to get status for
     */
    requestDeviceStatus(deviceId) {
        if (!this.connected) {
            console.warn('Cannot request device status: not connected');
            return false;
        }
        
        this.socket.emit('request_device_status', { device_id: deviceId });
        return true;
    }
    
    /**
     * Register an event handler
     * @param {string} event - Event name to listen for
     * @param {function} callback - Function to call when event occurs
     */
    on(event, callback) {
        if (!this.eventHandlers[event]) {
            this.eventHandlers[event] = [];
        }
        this.eventHandlers[event].push(callback);
    }
    
    /**
     * Remove an event handler
     * @param {string} event - Event name to remove handler for
     * @param {function} callback - Function to remove (if not provided, all handlers for the event are removed)
     */
    off(event, callback) {
        if (!this.eventHandlers[event]) {
            return;
        }
        
        if (!callback) {
            // Remove all handlers for this event
            delete this.eventHandlers[event];
        } else {
            // Remove specific handler
            this.eventHandlers[event] = this.eventHandlers[event].filter(cb => cb !== callback);
        }
    }
    
    /**
     * Trigger an event and call all registered handlers
     * @param {string} event - Event name to trigger
     * @param {*} data - Data to pass to event handlers
     * @private
     */
    _triggerEvent(event, data) {
        if (!this.eventHandlers[event]) {
            return;
        }
        
        for (const callback of this.eventHandlers[event]) {
            try {
                callback(data);
            } catch (error) {
                console.error(`Error in ${event} event handler:`, error);
            }
        }
    }
}

// Create a global instance for easy access
const deviceSocket = new SocketIOClient();

// Auto-connect when the page loads
document.addEventListener('DOMContentLoaded', () => {
    // Only auto-connect on pages that need device monitoring
    if (document.querySelector('.device-select') || 
        document.querySelector('.device-frame') ||
        document.querySelector('.device-monitor')) {
        deviceSocket.connect();
    }
});

// Disconnect when the page unloads
window.addEventListener('beforeunload', () => {
    if (deviceSocket && deviceSocket.connected) {
        deviceSocket.disconnect();
    }
});